<template>
	<div class="material-list-view">
		<!-- 搜索区域 -->
		<el-form :model="searchData" class="search-form">
			<div class="search-content">
				<!-- 第一行：基础搜索字段 -->
				<div class="search-row">
					<div class="search-group">
						<label class="search-label">物料信息</label>
						<div class="search-inputs">
							<el-input
								v-model="searchData.Name"
								placeholder="物料名称"
								clearable
								:prefix-icon="Search"
								@keyup.enter="handleSearch"
								class="search-input"
							/>
							<el-input v-model="searchData.Code" placeholder="物料编码" clearable @keyup.enter="handleSearch" class="search-input" />
						</div>
					</div>
				</div>

				<!-- 第二行：ERP相关字段 -->
				<div class="search-row">
					<div class="search-group">
						<label class="search-label">ERP信息</label>
						<div class="search-inputs">
							<el-input v-model="searchData.ErpId" placeholder="ERP物料编码" clearable @keyup.enter="handleSearch" class="search-input" />
							<el-input v-model="searchData.ErpName" placeholder="ERP物料名称" clearable @keyup.enter="handleSearch" class="search-input" />
							<el-input v-model="searchData.ErpModel" placeholder="ERP物料型号" clearable @keyup.enter="handleSearch" class="search-input" />
						</div>
					</div>
				</div>

				<!-- 第三行：SKU相关字段 -->
				<div class="search-row">
					<div class="search-group">
						<label class="search-label">SKU信息</label>
						<div class="search-inputs">
							<el-input v-model="searchData.SkuName" placeholder="SKU名称" clearable @keyup.enter="handleSearch" class="search-input" />
							<el-input v-model="searchData.SkuCode" placeholder="SKU编码" clearable @keyup.enter="handleSearch" class="search-input" />
						</div>
					</div>
				</div>

				<!-- 操作按钮 -->
				<div class="search-actions">
					<el-button type="primary" :icon="Search" @click="handleSearch" class="search-btn"> 搜索 </el-button>
					<el-button :icon="Refresh" @click="handleReset" class="reset-btn"> 重置 </el-button>
				</div>
			</div>
		</el-form>

		<!-- 物料表格 -->
		<el-table
			v-loading="loading"
			:data="dataList"
			stripe
			border
			highlight-current-row
			max-height="350"
			class="material-table"
			@row-click="handleRowClick"
		>
			<el-table-column type="index" label="序号" width="45" align="center" />
			<el-table-column prop="Name" label="物料信息" min-width="140" show-overflow-tooltip>
				<template #default="{ row }">
					<div class="name-cell">
						<el-tag size="small" type="success" effect="plain">{{ row.Code }}</el-tag>
						<span class="name-text">{{ row.Name }}</span>
					</div>
				</template>
			</el-table-column>
			<el-table-column prop="MaterialGroupName" label="分类" width="100" show-overflow-tooltip />
			<el-table-column prop="Description" label="详情" min-width="150" show-overflow-tooltip />
			<el-table-column prop="State" label="状态" width="70" align="center">
				<template #default="{ row }">
					<el-tag :type="row.State === '启用' ? 'success' : 'info'" size="small">{{ row.State }}</el-tag>
				</template>
			</el-table-column>
			<el-table-column prop="UnitName" label="单位" width="80" align="center" />
			<el-table-column label="操作" width="90" align="center" fixed="right">
				<template #default="{ row }">
					<el-button type="primary" link size="small" @click.stop="handleSelect(row)">
						{{ props.allowDirectSelect ? '选择' : '选取型号' }} <el-icon class="el-icon--right"><ArrowRight /></el-icon>
					</el-button>
				</template>
			</el-table-column>
		</el-table>

		<!-- 分页 -->
		<div class="pagination-container">
			<el-pagination
				v-model:current-page="pagination.currentPage"
				v-model:page-size="pagination.pageSize"
				:page-sizes="[10, 20, 50, 100, 200]"
				:total="pagination.total"
				size="small"
				layout="total, sizes, prev, pager, next, jumper"
				@size-change="handleSizeChange"
				@current-change="handlePageChange"
			/>
		</div>
	</div>
</template>

<script setup lang="ts">
import { ref, reactive, watch, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { Search, Refresh, ArrowRight } from '@element-plus/icons-vue';
import type { ISysMaterialView } from './types';

/**
 * ==================== Props & Emits ====================
 */
interface Props {
	/** API 实例 */
	api: any;
	/** 额外的过滤条件 */
	filters?: Record<string, any>;
	/** 搜索状态（用于恢复搜索条件） */
	searchState?: {
		Name?: string;
		Code?: string;
		State?: string;
		ErpId?: string;
		ErpName?: string;
		ErpModel?: string;
		currentPage?: number;
		pageSize?: number;
	};
	/** 是否允许直接选择物料（影响按钮文本显示） */
	allowDirectSelect?: boolean;
}

interface Emits {
	/** 物料选择事件 */
	(e: 'select', material: ISysMaterialView): void;
	/** 搜索条件变化事件 */
	(
		e: 'search-change',
		searchData: { Name: string; Code: string; State: string; ErpId: string; ErpName: string; ErpModel: string; currentPage: number; pageSize: number }
	): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

/**
 * ==================== 搜索相关 ====================
 */
// 搜索表单数据（支持从 props 恢复状态）
const searchData = reactive({
	Name: props.searchState?.Name || '',
	Code: props.searchState?.Code || '',
	State: props.searchState?.State || '',
	ErpId: props.searchState?.ErpId || '',
	ErpName: props.searchState?.ErpName || '',
	ErpModel: props.searchState?.ErpModel || '',
});

/**
 * ==================== 数据与缓存 ====================
 */
// 物料列表数据
const dataList = ref<ISysMaterialView[]>([]);
// 加载状态
const loading = ref(false);
// 搜索防抖定时器
const searchTimer = ref<NodeJS.Timeout | null>(null);
const SEARCH_DEBOUNCE_DELAY = 500; // 搜索防抖延迟：500ms

// 数据缓存（提升性能，减少重复请求）
const dataCache = ref<Map<string, { data: ISysMaterialView[]; total: number; timestamp: number }>>(new Map());
const CACHE_DURATION = 5 * 60 * 1000; // 缓存有效期：5分钟

/**
 * 生成缓存键
 * @description 基于搜索参数和过滤条件生成唯一的缓存键
 */
const generateCacheKey = (searchParams: any): string => {
	return JSON.stringify({
		Name: searchParams.Name || '',
		Code: searchParams.Code || '',
		State: searchParams.State || '',
		ErpId: searchParams.ErpId || '',
		ErpName: searchParams.ErpName || '',
		ErpModel: searchParams.ErpModel || '',
		Page: searchParams.Page || 1,
		Limit: searchParams.Limit || 50,
		...props.filters,
	});
};

/**
 * 清理过期缓存
 * @description 遍历缓存，删除超过有效期的数据
 */
const cleanExpiredCache = (): void => {
	const now = Date.now();
	for (const [key, value] of dataCache.value.entries()) {
		if (now - value.timestamp > CACHE_DURATION) {
			dataCache.value.delete(key);
		}
	}
};

/**
 * ==================== 分页 ====================
 */
const pagination = reactive({
	currentPage: props.searchState?.currentPage || 1,
	pageSize: props.searchState?.pageSize || 50,
	total: 0,
});

/**
 * ==================== 数据加载 ====================
 */
/**
 * 加载物料列表数据
 * @param forceRefresh - 是否强制刷新（跳过缓存）
 */
const loadData = async (forceRefresh = false): Promise<void> => {
	try {
		loading.value = true;

		// 合并搜索参数和过滤条件
		const searchParams = {
			...searchData,
			...props.filters,
			Page: pagination.currentPage,
			Limit: pagination.pageSize,
		};

		const cacheKey = generateCacheKey(searchParams);
		const now = Date.now();

		// 检查缓存（非强制刷新时）
		if (!forceRefresh && dataCache.value.has(cacheKey)) {
			const cached = dataCache.value.get(cacheKey)!;
			// 缓存未过期，直接使用
			if (now - cached.timestamp < CACHE_DURATION) {
				dataList.value = cached.data;
				pagination.total = cached.total;
				return;
			}
		}

		// 调用 API 获取数据
		const response: any = await props.api.search(searchParams);

		// 处理响应数据（后端返回格式：{ Data: [], Count: number }）
		if (Array.isArray(response.Data)) {
			dataList.value = response.Data;
			pagination.total = response.Count || response.Total || 0;

			// 缓存结果
			dataCache.value.set(cacheKey, {
				data: response.Data,
				total: pagination.total,
				timestamp: now,
			});
		}
	} catch (error) {
		console.error('加载物料列表失败:', error);
		ElMessage.error('加载物料列表失败');
		dataList.value = [];
	} finally {
		loading.value = false;
	}
};

/**
 * ==================== 事件处理 ====================
 */
/**
 * 发送搜索状态变化事件（用于父组件保存搜索状态）
 */
const emitSearchChange = (): void => {
	emit('search-change', {
		Name: searchData.Name,
		Code: searchData.Code,
		State: searchData.State,
		ErpId: searchData.ErpId,
		ErpName: searchData.ErpName,
		ErpModel: searchData.ErpModel,
		currentPage: pagination.currentPage,
		pageSize: pagination.pageSize,
	});
};

/**
 * 搜索按钮点击
 */
const handleSearch = (): void => {
	// 清除防抖定时器
	if (searchTimer.value) {
		clearTimeout(searchTimer.value);
		searchTimer.value = null;
	}
	pagination.currentPage = 1; // 重置到第一页
	loadData(true); // 强制刷新，获取最新数据
	emitSearchChange();
};

/**
 * 重置按钮点击
 */
const handleReset = (): void => {
	// 清空所有搜索条件
	Object.assign(searchData, {
		Name: '',
		Code: '',
		State: '',
		ErpId: '',
		ErpName: '',
		ErpModel: '',
	});
	pagination.currentPage = 1; // 重置到第一页
	loadData(true); // 强制刷新
	emitSearchChange();
};

/**
 * 分页页码变化
 */
const handlePageChange = (page: number): void => {
	pagination.currentPage = page;
	loadData(); // 可以使用缓存
	emitSearchChange();
};

/**
 * 分页大小变化
 */
const handleSizeChange = (size: number): void => {
	pagination.pageSize = size;
	pagination.currentPage = 1; // 重置到第一页
	loadData(); // 可以使用缓存
	emitSearchChange();
};

/**
 * 选择物料（按钮点击）
 */
const handleSelect = (row: ISysMaterialView): void => {
	emit('select', row);
};

/**
 * 选择物料（行点击）
 */
const handleRowClick = (row: ISysMaterialView): void => {
	emit('select', row);
};

/**
 * ==================== 监听器 ====================
 */
// 监听搜索条件变化，使用防抖自动搜索
watch(
	[() => searchData.Name, () => searchData.Code, () => searchData.State, () => searchData.ErpId, () => searchData.ErpName, () => searchData.ErpModel],
	() => {
		// 清除之前的定时器
		if (searchTimer.value) {
			clearTimeout(searchTimer.value);
		}
		// 设置新的防抖定时器
		searchTimer.value = setTimeout(() => {
			pagination.currentPage = 1;
			loadData(true); // 搜索时强制刷新
			emitSearchChange();
		}, SEARCH_DEBOUNCE_DELAY);
	},
	{ deep: true }
);

// 监听过滤条件变化，自动重新加载数据
watch(
	() => props.filters,
	() => {
		pagination.currentPage = 1;
		loadData();
	},
	{ deep: true }
);

/**
 * ==================== 对外暴露 ====================
 */
defineExpose({
	loadData, // 暴露加载方法供父组件调用
	reset: handleReset, // 暴露重置方法
});

/**
 * ==================== 生命周期 ====================
 */
onMounted(() => {
	cleanExpiredCache(); // 清理过期缓存
	loadData(); // 初始化加载数据
});
</script>

<style scoped lang="scss">
.material-list-view {
	padding: 10px;

	.search-form {
		margin-bottom: 8px;
		background: var(--el-fill-color-blank);
		border: 1px solid var(--el-border-color-lighter);
		border-radius: 4px;
		transition: all 0.2s;

		&:hover {
			border-color: var(--el-border-color-light);
		}

		.search-content {
			padding: 8px 12px;
		}

		.search-row {
			margin-bottom: 8px;

			&:last-of-type {
				margin-bottom: 0;
			}
		}

		.search-group {
			display: flex;
			align-items: center;
			gap: 8px;

			@media (max-width: 768px) {
				flex-direction: column;
				align-items: flex-start;
				gap: 4px;
			}
		}

		.search-label {
			min-width: 60px;
			font-size: 12px;
			font-weight: 500;
			color: var(--el-text-color-primary);
			white-space: nowrap;

			@media (max-width: 768px) {
				min-width: auto;
			}
		}

		.search-inputs {
			flex: 1;
			display: grid;
			grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
			gap: 6px;

			@media (max-width: 1200px) {
				grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
			}

			@media (max-width: 768px) {
				grid-template-columns: 1fr;
				gap: 4px;
			}
		}

		.search-input {
			:deep(.el-input__wrapper) {
				border-radius: 4px;
				box-shadow: 0 0 0 1px var(--el-border-color) inset;
				transition: all 0.2s;
				font-size: 12px;
				height: 28px;
				background: var(--el-fill-color-blank);

				&:hover {
					box-shadow: 0 0 0 1px var(--el-border-color-hover) inset;
				}

				&.is-focus {
					box-shadow: 0 0 0 1px var(--el-color-primary) inset;
				}

				.el-input__inner {
					font-size: 12px;
					color: var(--el-text-color-primary);

					&::placeholder {
						color: var(--el-text-color-placeholder);
						font-size: 12px;
					}
				}

				.el-input__prefix,
				.el-input__suffix {
					.el-input__prefix-inner,
					.el-input__suffix-inner {
						.el-icon {
							font-size: 12px;
							color: var(--el-text-color-placeholder);
						}
					}
				}
			}
		}

		.search-actions {
			display: flex;
			justify-content: flex-end;
			align-items: center;
			gap: 6px;
			padding-top: 6px;
			border-top: 1px solid var(--el-border-color-lighter);
			margin-top: 8px;

			@media (max-width: 768px) {
				justify-content: center;
			}

			.search-btn,
			.reset-btn {
				min-width: 60px;
				height: 28px;
				font-size: 12px;
				font-weight: 500;
				border-radius: 4px;
				padding: 0 12px;
				transition: all 0.2s;

				@media (max-width: 768px) {
					min-width: 80px;
				}
			}

			.search-btn {
				background: var(--el-color-primary);
				border: none;
				color: #fff;

				&:hover {
					background: var(--el-color-primary-light-3);
				}
			}

			.reset-btn {
				background: var(--el-fill-color-blank);
				border: 1px solid var(--el-border-color);
				color: var(--el-text-color-regular);

				&:hover {
					background: var(--el-fill-color-light);
					border-color: var(--el-color-primary-light-5);
					color: var(--el-color-primary);
				}
			}
		}
	}

	.material-table {
		border: 1px solid var(--el-border-color-lighter);
		border-radius: 4px;
		overflow: hidden;
		box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
		background: var(--el-fill-color-blank);

		:deep(.el-table) {
			background: transparent;
		}

		// 空状态优化
		:deep(.el-table__empty-block) {
			padding: 30px 0;
		}

		:deep(.el-table__empty-text) {
			color: var(--el-text-color-placeholder);
			font-size: 12px;
		}

		// 加载状态优化
		:deep(.el-loading-mask) {
			background-color: rgba(255, 255, 255, 0.8);
			backdrop-filter: blur(2px);
		}

		:deep(.el-table__header) {
			th {
				background: linear-gradient(180deg, var(--el-fill-color-blank) 0%, var(--el-fill-color-light) 100%);
				font-size: 12px;
				font-weight: 600;
				padding: 6px 0;
				color: var(--el-text-color-primary);
				border-bottom: 1px solid var(--el-border-color-light);

				.cell {
					padding: 0 8px;
				}
			}
		}

		:deep(.el-table__body) {
			td {
				font-size: 12px;
				padding: 6px 0;
				border-bottom: 1px solid var(--el-border-color-lighter);

				.cell {
					padding: 0 8px;
				}
			}
		}

		:deep(.el-table__row) {
			cursor: pointer;
			transition: all 0.2s;
			background: var(--el-fill-color-blank);

			&:hover {
				background: var(--el-color-primary-light-9) !important;

				.name-text {
					color: var(--el-color-primary);
				}
			}

			&:last-child td {
				border-bottom: none;
			}
		}

		.name-cell {
			display: flex;
			align-items: baseline;
			gap: 6px;

			.el-tag {
				font-weight: 500;
				border-radius: 3px;
				font-size: 11px;
				padding: 0 6px;
				height: 18px;
				line-height: 18px;
				display: inline-flex;
				align-items: center;
			}

			.name-text {
				flex: 1;
				font-weight: 500;
				color: var(--el-text-color-primary);
				transition: color 0.2s;
				line-height: 18px;
			}
		}

		:deep(.el-button--primary.is-link) {
			font-weight: 500;
			font-size: 12px;
			transition: all 0.2s;
			padding: 2px 6px;

			&:hover {
				color: var(--el-color-primary-light-3);
			}
		}
	}

	.pagination-container {
		margin-top: 8px;
		display: flex;
		justify-content: flex-end;
		padding: 6px 0;

		:deep(.el-pagination) {
			.btn-prev,
			.btn-next,
			.el-pager li {
				min-width: 26px;
				height: 26px;
				line-height: 26px;
				border-radius: 4px;
				transition: all 0.2s;
				font-size: 12px;
				margin: 0 2px;

				&:not(.is-disabled):hover {
					background-color: var(--el-color-primary-light-9);
					color: var(--el-color-primary);
				}
			}

			.el-pager li {
				&.is-active {
					background: var(--el-color-primary);
					font-weight: 600;
					color: #fff;
				}
			}

			.btn-prev,
			.btn-next {
				background-color: var(--el-fill-color-blank);
				border: 1px solid var(--el-border-color);

				&.is-disabled {
					opacity: 0.5;
					cursor: not-allowed;
				}
			}
		}
	}
}
</style>
